package com.example.ymm.modules1.service.impl.user;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.Master;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.ymm.base.BaseServiceImpl;
import com.example.ymm.model.TableList;
import com.example.ymm.model.YmPageDto;
import com.example.ymm.modules1.entity.my.user.*;
import com.example.ymm.modules1.mapper.my.user.DbUserNoteMapper;
import com.example.ymm.modules1.service.dto.*;
import com.example.ymm.modules1.service.user.*;
import com.example.ymm.util.*;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional
@Slf4j
@Master
public class DbUserNoteServiceImpl extends BaseServiceImpl<DbUserNoteMapper, DbUserNote> implements DbUserNoteService {

    @Autowired
    DbFileService dbFileService;

    @Autowired
    DbCardService dbCardService;

    @Autowired
    DbIntegralLogService dbIntegralLogService;

    @Autowired
    DbUserService dbUserService;

    @Autowired
    DbOrderService dbOrderService;


    @Value("${spring.profiles.active}")
    String PD_MATCH;

    @Override
    public TableList<DbUserNote> list(DbUserNoteQueryCriteria criteria, YmPageDto pageDto) {
        IPage<DbUserNote> page = new Page<DbUserNote>(pageDto.getPage(), pageDto.getPageSize());
        QueryWrapper predicate = QueryHelpPlus.getPredicate(DbUserNote.class, criteria);
        predicate.orderByDesc("create_time");
        baseMapper.selectPage(page, predicate);
        TableList<DbUserNote> tableList = new TableList(page);
        // List<DbUserNote> list = tableList.getList();
        // list.forEach(r->{
        // DbFile dbFile = dbFileService.getByNoteId(r.getNoteId());
        // r.setDbFile(dbFile);
        // });
        return tableList;
    }

    public List<DbUserNote> queryAll(DbUserNoteQueryCriteria criteria) {
        List<DbUserNote> result = baseMapper.selectList(QueryHelpPlus.getPredicate(DbUserNote.class, criteria));
        return result;
    }

    @Override
    public DbUserNote getNewUserNote(DbUserNoteQueryCriteria criteria) {
        return baseMapper.getNewUserNote(criteria);
    }

    @Override
    public List<String> getTimes(String time) {
        String start = time + " 00:00:00";
        String end = time + " 23:59:59";
        List<String> list = new ArrayList<>();
        list.add(start);
        list.add(end);
        return list;
    }

    @Override
    public BigDecimal getUserDurations(DbUserNoteQueryCriteria criteria) {
        return baseMapper.getUserDurations(criteria);
    }

    @Override
    public List<JSONObject> getNotesByBookId(String bookId, String userId) {
        DbUserNoteQueryCriteria criteria = new DbUserNoteQueryCriteria();
        // String userId = getUserId();
        criteria.setUserId(userId);
        criteria.setBookId(bookId);
        List<DbUserNote> dbUserNotes = queryAll(criteria);
        List<JSONObject> result = new ArrayList<>();
        Map<String, String> timeMap = new LinkedHashMap<>();
        dbUserNotes.forEach(r -> {
            String formattedTimestamp = getFormattedTimes(r.getCreateTime());
            r.setFormatDate(formattedTimestamp);
            timeMap.put(formattedTimestamp, formattedTimestamp);
        });
        Iterator<Map.Entry<String, String>> iterator = timeMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            // String key = entry.getKey();
            String value = entry.getValue();
            JSONObject json = new JSONObject();
            json.put("time", value);
            List<DbUserNote> list = new ArrayList<>();
            dbUserNotes.forEach(r -> {
                if (value.equals(r.getFormatDate())) {
                    list.add(r);
                }
            });
            json.put("list", list);
            result.add(json);
        }

        return result;
    }

    public String getFormattedTimes(Timestamp createTime) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        // 使用format方法格式化Timestamp
        String formattedTimestamp = formatter.format(createTime);
        return formattedTimestamp;
    }

    @Override
    public Map<String, AddNoteResultDto> addNoteBatch(List<DbUserNoteDto> list) {
        Map<String, AddNoteResultDto> result = new HashMap<>();
        DbUserNoteDto dbUserNoteDto = list.get(0);
        String userId = dbUserNoteDto.getUserId();

        // 读书累计积分 type =1 时进行提示
        AddNoteResultDto readMap = dbIntegralLogService.addReadTypeByToday(list);
        AddNoteResultDto daysMap=new AddNoteResultDto();
        daysMap.setType(0);
        AddNoteResultDto fullMap =new AddNoteResultDto();
        fullMap.setType(0);

        //可进行打卡
        if (readMap.getType().equals(1)) {
            Date now = new Date();
            String day = DateKit.dateFormat(now, "yyyy-MM-dd");
            DbCardQueryCriteria criteria=new DbCardQueryCriteria();
            criteria.setDay(day);
            criteria.setUserId(userId);
            //查询打卡记录
            List<DbCard> dbCards = dbCardService.queryAll(criteria);
            if(UtilValidate.isEmpty(dbCards)){
                // 打卡连续天数积分 type =1 时进行提示;添加积分前先查询打卡记录 ；此方法需要在 dbCardService.addCard()前执行
                daysMap = dbIntegralLogService.queryCardByToday(list);

                // 打卡
                DbCard card = dbCardService.addCard();

                // 满勤 type =1 时进行提示
                fullMap = dbIntegralLogService.queryFullByToday(card);
            }


        }


        // 计算积分
        Integer integral = 0;
        if (UtilValidate.isNotEmpty(fullMap)&&fullMap.getType().equals(1)) {
            integral += fullMap.getIntegral();
        }

        if (UtilValidate.isNotEmpty(readMap)&&readMap.getType().equals(1)) {
            integral += readMap.getIntegral();
        }
        if (UtilValidate.isNotEmpty(daysMap)&&daysMap.getType().equals(1)) {
            integral += daysMap.getIntegral();
        }

        if (integral > 0) {
            // 添加积分
            DbUser user = dbUserService.getById(userId);
            Integer total = user.getIntegral() + integral;
            user.setIntegral(total);
            dbUserService.saveOrUpdate(user);
        }

        List<DbUserNote> adds = new ArrayList<>();
        for (DbUserNoteDto r : list) {
            DbUserNote userNote = new DbUserNote();
            BeanUtils.copyProperties(r, userNote);
            Date now = new Date();
            String day = DateKit.dateFormat(now, "yyyy-MM-dd");
            // String day = DateUtils.getDateStrByBefore8_30();
            userNote.setDay(day);
            adds.add(userNote);
        }
        saveOrUpdateBatch(adds);

        if (readMap.getType().equals(1)) {
            //是否进入当月前5
            Integer rankingNum = dbCardService.getThisMonthRankings();
            log.info("--正常打卡前5："+getUserName()+"-名次:"+rankingNum);
            readMap.setRankingNum(rankingNum);
        }

        // 开启一个异步线程来同步上传mp3
        Thread thread = new Thread(() -> {
            for (DbUserNote r : adds) {
                String s = syncUpUserNoteByOne(r);
                if (UtilValidate.isNotEmpty(s)) {
                    r.setMp3Url(s);
                    saveOrUpdate(r);
                }
            }
        });
        if("prod-new".equals(PD_MATCH)){
            thread.start();
        }
        // 合并
        mgMap(result, "fullMap", fullMap);
        mgMap(result, "readMap", readMap);
        mgMap(result, "daysMap", daysMap);

        return result;
    }

    @Override
    public Map<String, AddNoteResultDto> patchNoteBatch(List<DbUserNoteDto> list, String date) {

        String userId = getUserId();

//        Integer todayPatchCards = dbCardService.getTodayPatchCards();
//        // 今天如果有补卡就不能再补了，一天最多只能补一次
//        if (UtilValidate.isNotEmpty(todayPatchCards) && todayPatchCards > 0) {
//            throw new RuntimeException("今天已经补过卡了哦，明天再来吧!");
//        }

        Map<String, AddNoteResultDto> result = new HashMap<>();

        // 目前只有一个读书累计积分
        AddNoteResultDto readMap = dbIntegralLogService.patchReadTypeByToday(list, date);

        //满勤
        AddNoteResultDto fullMap =new AddNoteResultDto();
        fullMap.setType(0);

        // 计算积分
        Integer integral = 0;
        if (readMap.getType().equals(1)) {
            integral += readMap.getIntegral();
        }

        if (integral > 0) {
            System.out.println("----添加积分::" + integral);
            // 添加积分
            DbUser user = dbUserService.getById(userId);
            Integer total = user.getIntegral() + integral;
            user.setIntegral(total);
            dbUserService.saveOrUpdate(user);
            // 生成打卡记录
           // DbCard card = dbCardService.addCardByDate(date);
        }

        //查询有没有打过卡
        Date now = new Date();
        now = DateKit.dateFormat(DateKit.dateFormat(now, date + " HH:mm:ss"));
        String day = date;
        DbCardQueryCriteria criteria = new DbCardQueryCriteria();
        criteria.setDay(day);
        criteria.setUserId(userId);
        List<DbCard> dbCards = dbCardService.queryAll(criteria);
        if(readMap.getType().equals(1)&&UtilValidate.isEmpty(dbCards)){
            // 生成打卡记录
            DbCard card = dbCardService.addCardByDate(date);
           // 满勤 type =1 时进行提示
            fullMap = dbIntegralLogService.queryFullByDate(card,date);
        }

        List<DbUserNote> adds = new ArrayList<>();
        for (DbUserNoteDto r : list) {
            DbUserNote userNote = new DbUserNote();
            BeanUtils.copyProperties(r, userNote);
            // Date now = new Date();
            // String day = DateKit.dateFormat(now, "yyyy-MM-dd");
            userNote.setDay(date);
            userNote.setSysNote("补卡");
            adds.add(userNote);
        }
        saveOrUpdateBatch(adds);
        // 开启一个异步线程来同步上传mp3
        Thread thread = new Thread(() -> {
            for (DbUserNote r : adds) {
                String s = syncUpUserNoteByOne(r);
                if (UtilValidate.isNotEmpty(s)) {
                    r.setMp3Url(s);
                    saveOrUpdate(r);
                }

            }
        });
        if("prod-new".equals(PD_MATCH)){
            thread.start();
        }
        mgMap(result, "readMap", readMap);
        mgMap(result, "fullMap", fullMap);
        return result;
    }

    public void mgMap(Map<String, AddNoteResultDto> result, String key, AddNoteResultDto item) {
        if (result.containsKey(key)) {
            AddNoteResultDto fullMap1 = result.get(key);
            if (item.getType().equals(1)) {
                fullMap1.setType(1);
                if (UtilValidate.isNotEmpty(fullMap1.getIntegral())) {
                    fullMap1.setIntegral(fullMap1.getIntegral() + item.getIntegral());
                } else {
                    fullMap1.setIntegral(item.getIntegral());
                }
                fullMap1.setNote(item.getNote());
                result.put(key, fullMap1);
            }
        } else {
            result.put(key, item);
        }

    }


    @Override
    public Map<String, AddNoteResultDto> advanceNoteBatch(List<DbUserNoteDto> list, String date) {
        Map<String, AddNoteResultDto> result = new HashMap<>();
    //    DbUserNoteDto dbUserNoteDto = list.get(0);
        String userId = getUserId();
        String userName = getUserName();
        //1 读书时长有没有达标： 读书累计积分 type =1 时进行提示
        AddNoteResultDto readMap = dbIntegralLogService.advanceReadTypeByToday(list,date);
        AddNoteResultDto daysMap=new AddNoteResultDto();
        daysMap.setType(0);
        AddNoteResultDto fullMap =new AddNoteResultDto();
        fullMap.setType(0);

        //可进行打卡
        if (readMap.getType().equals(1)) {
//            Date now = new Date();
//            String day = DateKit.dateFormat(now, "yyyy-MM-dd");
            DbCardQueryCriteria criteria=new DbCardQueryCriteria();
            criteria.setDay(date);
            criteria.setUserId(userId);
            //查询打卡记录
            List<DbCard> dbCards = dbCardService.queryAll(criteria);
            if(UtilValidate.isEmpty(dbCards)){
                //2 打卡连续天数 计算  type =1 时进行提示;添加积分前先查询打卡记录 ；此方法需要在 dbCardService.addCard()前执行
                daysMap = dbIntegralLogService.queryAdvanceCardByDate(list,date);

                // 打卡
                DbCard card = dbCardService.addAdvanceCardByDate(date);


                // 满勤 type =1 时进行提示
                fullMap = dbIntegralLogService.queryFullByDate(card,date);
            }


        }


        // 计算积分
        Integer integral = 0;
        if (UtilValidate.isNotEmpty(fullMap)&&fullMap.getType().equals(1)) {
            integral += fullMap.getIntegral();
        }

        if (UtilValidate.isNotEmpty(readMap)&&readMap.getType().equals(1)) {
            integral += readMap.getIntegral();
        }
        if (UtilValidate.isNotEmpty(daysMap)&&daysMap.getType().equals(1)) {
            integral += daysMap.getIntegral();
        }

        if (integral > 0) {
            // 添加积分
            DbUser user = dbUserService.getById(userId);
            Integer total = user.getIntegral() + integral;
            user.setIntegral(total);
            dbUserService.saveOrUpdate(user);
        }

        List<DbUserNote> adds = new ArrayList<>();
        for (DbUserNoteDto r : list) {
            DbUserNote userNote = new DbUserNote();
            BeanUtils.copyProperties(r, userNote);
//            Date now = new Date();
//            String day = DateKit.dateFormat(now, "yyyy-MM-dd");
            // String day = DateUtils.getDateStrByBefore8_30();
            userNote.setDay(date);
            userNote.setSysNote("提前读书");
            userNote.setUserId(userId);
            userNote.setUserName(userName);
            adds.add(userNote);
        }
        saveOrUpdateBatch(adds);
        if (readMap.getType().equals(1)) {
            //是否进入当月前5
            Integer rankingNum = dbCardService.getThisMonthRankings();
            log.info("--打卡前5："+getUserName()+"-名次:"+rankingNum);
            readMap.setRankingNum(rankingNum);
        }


        // 开启一个异步线程来同步上传mp3
        Thread thread = new Thread(() -> {
            for (DbUserNote r : adds) {
                String s = syncUpUserNoteByOne(r);
                if (UtilValidate.isNotEmpty(s)) {
                    r.setMp3Url(s);
                    saveOrUpdate(r);
                }
            }
        });
        if("prod-new".equals(PD_MATCH)){
            thread.start();
        }
        // 合并
        mgMap(result, "fullMap", fullMap);
        mgMap(result, "readMap", readMap);
        mgMap(result, "daysMap", daysMap);

        return result;
    }

    @Override
    public void deleteNote(String noteId) {
        removeById(noteId);
//        LambdaQueryWrapper<DbFile> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(DbFile::getNoteId, noteId);
//        dbFileService.remove(queryWrapper);
    }

    @Override
    public List<DbCard> testGetUserNote() {
        DbUserNoteQueryCriteria noteQuery = new DbUserNoteQueryCriteria();
        // String start="2024-08-01 00:00:00";
        // String end="2024-08-06 11:20:59";
        // List<String> list=new ArrayList<>();
        // list.add(start);
        // list.add(end);
        // noteQuery.setCreateTime(list);
        System.out.println("--开始同步;;");
        List<DbUserNote> dbUserNotes = queryAll(noteQuery);
        List<DbUserNote> notes = new ArrayList<>();
        for (int i = 0; i < dbUserNotes.size(); i++) {
            DbUserNote r = dbUserNotes.get(i);
            String s = syncUpUserNoteByOne(r);
            if (UtilValidate.isNotEmpty(s)) {
                r.setMp3Url(s);
                notes.add(r);
            }

        }
        saveOrUpdateBatch(notes);
        System.out.println("----已同步" + notes.size());
        return null;
        // System.out.println(dbUserNotes);
    }

    @Override
    public String syncUpUserNoteByOne(DbUserNote dbUserNote) {
        long start = System.currentTimeMillis();
        String url = FileUtil.uploadOggFn(dbUserNote.getRemoteUrl(), dbUserNote.getCreateTime());
        long end = System.currentTimeMillis();
        System.out.println(url);
        System.out.println("--耗时:" + ((end - start) / 1000f));
        return url;
    }

    @Override
    public List<BookPieDto> bookPieCount(SysRankingQueryCriteria criteria) {

        List<BookPieDto> bookPieDtos = baseMapper.bookPieCount(criteria);
        bookPieDtos.forEach(r -> {
            DbUserNoteQueryCriteria c = new DbUserNoteQueryCriteria();
            c.setBookId(r.getBookId());
            List<String> list = bookPieUserList(c);
            r.setUsers(list);
        });
        return bookPieDtos;
    }

    @Override
    public List<String> bookPieUserList(DbUserNoteQueryCriteria criteria) {
        return baseMapper.bookPieUserList(criteria);
    }


    @Override
    public Map<String, Object> bookUserTimeCount(SysRankingQueryCriteria criteria) {

        if(UtilValidate.isNotEmpty(criteria.getStartDate())&&UtilValidate.isNotEmpty(criteria.getEndDate())){
            List<String> items=new ArrayList<>();
            items.add(criteria.getStartDate());
            items.add(criteria.getEndDate());
            criteria.setTimes(items);
        }
        if(UtilValidate.isEmpty(criteria.getDateType())
        &&UtilValidate.isEmpty(criteria.getTimes())){
            criteria.setDateType("month");
            Date now=new Date();
            String s = DateKit.dateFormat(now, "yyyy-MM");
            criteria.setDateStr(s);
        }
        if(UtilValidate.isNotEmpty(criteria.getDateType())
                &&"year".equals(criteria.getDateType())
                &&UtilValidate.isNotEmpty(criteria.getDateStr())
        ){
            String s = criteria.getDateStr().split("-")[0];
            criteria.setDateStr(s);
        }
        //人数
        Integer userNum = baseMapper.userNumCount(criteria);
        //统计读书人次
        Integer numberOfTimes = baseMapper.userFrequencyCount(criteria);
        //统计读书时长
        Double timeLength = baseMapper.userTimeCount(criteria);

        Integer orderNum = dbOrderService.orderNumCount(criteria);

        //读书积分【新增】=读书+满勤+签到
        criteria.setIsSumRead(1);
        Integer bookIntegralTotal= dbIntegralLogService.sumIntegralTotal(criteria);

        //总积分【新增】=读书积分+表扬积分
        criteria.setIsSumRead(0);
        Integer allIntegralTotal= dbIntegralLogService.sumIntegralTotal(criteria);

        criteria.setDateType(null);
        //读书积分【累计】
        criteria.setIsSumRead(1);
        Integer bookIntegralAllTotal= dbIntegralLogService.sumIntegralTotal(criteria);
        //总积分【累计】
        criteria.setIsSumRead(0);
        Integer allIntegralAllTotal= dbIntegralLogService.sumIntegralTotal(criteria);

        //兑换积分(总积分)

        Double allConversionIntegral = dbOrderService.totalConversionIntegral(criteria);
        //剩余积分(总积分)
        Double allTotalResidue= dbIntegralLogService.allTotalResidue(criteria);

        Map<String,Object> map=new HashMap<>();
        map.put("userNum",userNum);
        map.put("numberOfTimes",numberOfTimes);
        map.put("timeLength",timeLength);
        map.put("orderNum",orderNum);
        map.put("bookIntegralTotal",UtilValidate.isNotEmpty(bookIntegralTotal)?bookIntegralTotal:0);
        map.put("allIntegralTotal",UtilValidate.isNotEmpty(allIntegralTotal)?allIntegralTotal:0);
        map.put("bookIntegralAllTotal",UtilValidate.isNotEmpty(bookIntegralAllTotal)?bookIntegralAllTotal:0);
        map.put("allIntegralAllTotal",UtilValidate.isNotEmpty(allIntegralAllTotal)?allIntegralAllTotal:0);

        map.put("allConversionIntegral",UtilValidate.isNotEmpty(allConversionIntegral)?allConversionIntegral:0);
        map.put("allTotalResidue",UtilValidate.isNotEmpty(allTotalResidue)?allTotalResidue:0);
        return map;
    }


    @Override
    public TableList<SysRankingListDto> sysRankingList(SysRankingQueryCriteria criteria, YmPageDto pageDto) {
        getPage(pageDto);
        List<SysRankingListDto> maps = baseMapper.sysRankingList(criteria);
        PageInfo<SysRankingListDto> pageInfo = new PageInfo<>(maps);
        TableList<SysRankingListDto> tableList=new TableList<>(pageInfo);
        return tableList;
    }
}
